package com.dayuanit.dy15.lesson24.demo2;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestIO {

    /**
     * 拷贝文件
     * @param srcPath 源文件的地址
     * @param targetPath 目标文件的地址
     */
    public static void copyFile(String srcPath, String targetPath) throws Exception {
        //TODO 读取文件到内存中 输入流
        FileInputStream fis = new FileInputStream(srcPath);

        //文件输出流
        FileOutputStream fos = new FileOutputStream(targetPath);

        //如何读取呢？
        int data = -1;

        //不停的读，直到返回值为-1，就到了文件的结尾。
        while (-1 != (data = fis.read())) {
            System.out.println(data);
            fos.write(data);
            fos.flush();//将管道里的数据写到磁盘里。
        }

        //关闭流 这是错误关闭流的方式。释放资源 否则的话 可能会导致系统的内存泄露
        fos.close();//不能够直接关闭 可能会有潜在的bug 比如空指针异常、IO流异常导致下面的关不了；这行代码未必能够执行到。
        fis.close();//error
    }

    /**
     *  通过byte数组，提高IO效率
     * @param srcPath
     * @param targetPath
     * @throws Exception
     */
    public static void copyFile2(String srcPath, String targetPath) {
        //之所以定义在try外面，是因为能够在finally代码块中对其可见
        FileInputStream fis = null;
        FileOutputStream fos = null;

        //不推荐 使用finally关闭流，太麻烦，啰嗦。
        try {
            fis = new FileInputStream(srcPath);
            fos = new FileOutputStream(targetPath);
            byte[] buff = new byte[1024];//1kb 相当于小桶，每次读取或者输出 都是小桶的容量，效率高
            int legnth = -1;

            while (-1 != (legnth = fis.read(buff))) {
//            fos.write(buff);
                fos.write(buff, 0, legnth);//读多少个字节，就写多少个字节，避免多写。
                fos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 字符流 拷贝纯文本文件
     * @param srcPath
     * @param targetPath
     * @throws Exception
     */
    public static void cpoyFile3(String srcPath, String targetPath) throws Exception {
        //字节转换成字符
        //jdk7提供的语法糖，将流声明在try()中，虚拟机会自动的将流关闭掉。那么我们代码就保持简洁性。
        //推荐 5颗星
        try (InputStreamReader isr = new InputStreamReader(new FileInputStream(srcPath), "GBK");
             OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(targetPath),"GBK");) {

            int data = -1;
            while (-1 != (data = isr.read())) {
                System.out.println(data + " " + (char)data);
                osw.write(data);
                osw.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 带小桶的字符流
     * @param srcPath
     * @param targetPath
     * @throws Exception
     */
    public static void cpoyFile4(String srcPath, String targetPath) throws Exception {
        try (InputStreamReader isr = new InputStreamReader(new FileInputStream(srcPath), "GBK");
             OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(targetPath), "GBK");) {
            char[] buff = new char[1024];
            int lenth = -1;
            while (-1 != (lenth = isr.read(buff))) {
                osw.write(buff, 0, lenth);
                osw.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 带缓冲的字符流
     * @param srcPath
     * @param targetPath
     * @throws Exception
     */
    public static void cpoyFile5(String srcPath, String targetPath) {
//        InputStreamReader isr = new InputStreamReader(new FileInputStream(srcPath));
//        BufferedReader br =  new BufferedReader(isr);//缓冲字符输入流

        try (
                BufferedReader br =  new BufferedReader(new InputStreamReader(new FileInputStream(srcPath),"GBK"));//缓冲字符输入流
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetPath), "GBK"));//缓冲字符输出流
                ) {
            String data = null;
            while (null != (data = br.readLine())) {
                System.out.println(data);
                bw.write(data);
                bw.newLine();//换行
                bw.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * http://cms-bucket.ws.126.net/2020/0226/8f5f8d4fj00q6arbf00bac000u001hcc.jpg
     * 访问网络上的资源 图片
     * @param resourceUrl
     */
    public static void copyFile6(String resourceUrl, String path) throws Exception {
        URL url = new URL(resourceUrl);

        try (
                InputStream inputStream = url.openStream();//打开一个网络输入流
                FileOutputStream fileOutputStream = new FileOutputStream(path);
                ) {
            byte[] buff = new byte[1024];
            int length = -1;
            while (-1 != (length = inputStream.read(buff))) {
                fileOutputStream.write(buff, 0, length);
                fileOutputStream.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 访问网络资源 一个网页  网页的本质就是由字符串组成的，这些字符串是HTML语言
     * @param resourceUrl
     * @param path
     */
    public static void copyFile7(String resourceUrl, String path) throws Exception {
        URL url = new URL(resourceUrl);

        //只有实现了AutoCloseable接口的close方法，才有资格定义在try()中。
        try (InputStream inputStream = url.openStream();
             BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "GBK"));
             BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), "GBK"));) {
            String data = null;

            while (null != (data = br.readLine())) {
                System.out.println(data);
                bw.write(data);
                bw.newLine();
                bw.flush();

                //提取文本中图片URL地址，进行下载
                List<String> imgUrlList = findImgUrl(data);
                for (String imgUrl : imgUrlList) {
                    String fileNmae = UUID.randomUUID().toString();
                    copyFile6(imgUrl, "D:/picture/pageImg/" + fileNmae + ".jpg");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 提取字符串中的图片URL地址
     * @param htmlMsg  HTML字符
     * @return 图片的URL地址
     */
    private static List<String> findImgUrl(String htmlMsg) {
        List<String> urlList = new ArrayList<>();

        String reg = "<img\\s+src=\"(http://[\\w./-]+)\"";

        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(htmlMsg);

        while (matcher.find()) {
            String imgUrl = matcher.group(1);
            System.out.println(imgUrl);
            urlList.add(imgUrl);
        }
        return urlList;
    }


    public static void main(String[] args) throws Exception {
        //1.先确定使用字节or字符：二进制的文件用字节流，纯文本的可以使用字符流
        //2.再确定是输入or输出
        //3.最后再确定操作的目标是文件、还是内存、还是网络、还是Java对象，操作的目标对象不一样，使用的功能流也就不一样。
        //4.如果你是个优秀的工程师，还要考虑要不要缓存，如果需要，就再包裹一层缓冲流。

        //注意：凡是File开头的流，都是访问的本地资源。


        //IO流 计算机底层知识 只要有信息交换的 基本上都要有IO流操作
        //文件的复制
//        copyFile("D:/picture/hanhan.jpeg", "D:/dayuanit/15/hanhan.jpeg");
//        copyFile("D:/picture/imitateWeb-master.zip", "D:/dayuanit/15/imitateWeb-master.zip");
//        copyFile2("D:/picture/gsl.jpg", "D:/picture/gsl3.jpg");
//        cpoyFile3("D:/picture/UserInfoController.java", "D:/picture/UserInfoController2.java");
//        cpoyFile3("D:/picture/user.txt", "D:/picture/user2.txt");
//        cpoyFile4("D:/picture/user.txt", "D:/picture/user2.txt");
//        cpoyFile5("D:/picture/user.txt", "D:/picture/user2.txt");
//        copyFile6("http://cms-bucket.ws.126.net/2020/0226/794b244ep00q6as1s008lc000gl009sc.png?imageView&thumbnail=550x0",
//                "D:/picture/163-2.jpg");

//        copyFile7("https://news.163.com/20/0226/14/F6AOUP9P000189FH.html", "D:/picture/163-page.html");
        copyFile7("https://news.163.com/20/0226/08/F6A3P6AM000189FH.html", "D:/picture/163-page.html");

//        String msg = "神内涵，不仅在直接谈及这四字之处，还体现在很多地方——</p><p class=\"f_center\"><img src=\"http://cms-bucket.ws.126.net/2020/0226/728b2a49j00q6arbf001qc000fh00c4c.jpg\" /></p><p>“经济社会是一个动态循环系统，不能长时间停摆”——这里体现着谨慎之心：" +
//                "要防止局部风险演化为区域性或全局性风险，防止短期风险演化为长期风险。</p><p>“推动医防结合，真正把问题解决在萌芽之时、成灾之前”——这是要把防微杜渐、主动化解风险的意识，更深入地体现在制度建设和治理能力建设中。</p><p class=\"f_center\"><img src=\"http://cms-bucket.ws.126.net/2020/0226/8f5f8d4fj00q6arbf00bac000u001hcc.jpg\" /></p><p>“必须";
//        //如何提取img的url地址呢？这就需要正则表达式。
//
//        String reg = "<img\\s+src=\"(http://[\\w./-]+)\"";
//
//        Pattern pattern = Pattern.compile(reg);
//        Matcher matcher = pattern.matcher(msg);
//
//        while (matcher.find()) {
//            System.out.println(matcher.group(1));
//        }

//        for (int i=0; i<100; i++) {
//            UUID uuid = UUID.randomUUID();
//            System.out.println(uuid.toString());
//        }


    }
}
